using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using JPR.TunelProxy.Interfaces;

namespace JPR.TunelProxy.Proxy.Implementations
{
    internal class SocketDatagramProvider : ISocketDatagramProvider
    {
        public Socket Socket
        {
            get { return _socket; }
            set { _socket = value; }
        }

        private Socket _socket;
        private SocketAsyncEventArgs sae;
        private EventHandler<NetworkProviderEventArgs> _receiveDataAsyncEventHandler;

        public SocketDatagramProvider():this(new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
        }

        public SocketDatagramProvider(Socket socket)
        {
            _socket = socket;
            sae = new SocketAsyncEventArgs();
            byte[] buffer = new byte[32768];
            sae.SetBuffer(buffer, 0, buffer.Length);
            sae.Completed += ReceiveDataAsyncCompleted;
        }

        #region Implementation of ISocketDatagramProvider

        public Stream ReceiveData()
        {
            MemoryStream stream = new MemoryStream();
            Byte[] buffer = new byte[1024];
            while (_socket.Available > 0)
            {
                int bytesReaded = _socket.Receive(buffer);
                stream.Write(buffer, 0, bytesReaded);
            }
            return stream;
        }

        public void SendData(Stream data)
        {
            int bytesReaded;
            byte[] buffer = new byte[1024];
            do
            {
                bytesReaded = data.Read(buffer, 0, buffer.Length);
                _socket.Send(buffer, 0, bytesReaded, SocketFlags.None);
            } while (bytesReaded>0);
        }

        public void ReceiveDataAsync(Stream data, EventHandler<NetworkProviderEventArgs> eventArgs)
        {
            _socket.ReceiveAsync(sae);
        }

        private void ReceiveDataAsyncCompleted(object sender, SocketAsyncEventArgs e)
        {
            throw new NotImplementedException();
        }

        public void Listen(int maxNumberOfConnection)
        {
            _socket.Listen(maxNumberOfConnection);
        }

        public void AcceptAsync(SocketAsyncEventArgs socketAsyncEventArgs)
        {
            _socket.AcceptAsync(socketAsyncEventArgs);
        }

        public void Bind(EndPoint ep)
        {
            _socket.Bind(ep);
        }

        public void Connect(EndPoint ep)
        {
            _socket.Connect(ep);
        }

        #endregion
    }
}